<?php
/**
 * @author all@cosmos-framework.org
 * @copyright (c) 2013 cosmos-framework.org
 * @license http://www.opensource.org/licenses/mit-license.php
 * @link http://cosmos-framework.org/
 * @package cosmos.framework
 * @version 2.0
 */
namespace Cosmos;

class Set extends \ArrayObject {

    /**
     * @param mixed[] $in
     */
    public function __construct($in = array()) {

        parent::__construct(self::_is($in) ? $in : array($in));
    }

    /**
     * @return string
     */
    public function __toString() {

        return implode($this->getArrayCopy());
    }

    /**
     * @param mixed[] $in
     * @return mixed[]
     */
    public static function keys($in) {

        $response = array();
        foreach ($in as $_ => &$v) {
            is_null($v) ? : $response[] = $_;
        }

        // response [].
        return $response;
    }

    /**
     * @param mixed[] $in
     * @return mixed
     */
    public static function load($in, $selector) {

        $p = explode(' ', $selector, 2);
        if ($in = &$in[$p[0]]) {
            if (isset($p[1])) {
                return self::load($in, $p[1]);
            }
        }
        return $in;
    }

    /**
     * @param string $selector
     * @return self
     */
    public function find($selector) {

        return new self(self::_find($this->getArrayCopy(), $selector));
    }

    /**
     * @param string $append
     * @param string $prepend
     * @return self
     */
    public function wrap($append, $prepend = null) {

        $response = array();
        foreach ($this->getArrayCopy() as $v) {
            $response[] = $prepend . $v . $append;
        }

        // response chain.
        return new self($response);
    }

    /**
     * @param string $selector
     * @return string[]
     */
    private static function _find($in, $selector) {

        $p = explode(' ', $selector, 2);

        if (strcmp($p[0], '*')) {
            if (isset($in[$p[0]])) {
                if (self::_is($in[$p[0]])) {
                    return self::_find($in[$p[0]], isset($p[1]) ? $p[1] : null);
                }

                return $in[$p[0]];
            }
            return null;
        }

        // *
        if (!empty($p[1])) {
            $response = array();
            foreach ((array) $in as $n) {
                if (!is_null($r = self::_find($n, $p[1]))) {
                    $response[] = $r;
                }
            }
            return $response;
        }
        return $in;
    }

    /**
     * @access private
     */
    private static function _is($in) {

        return is_array($in) || is_object($in);
    }

}
